// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using NUnit.Framework;
using SoapTrace.Core.Communication;
using SoapTrace.Core.Formatters;
using SoapTrace.Tests.Utils;
using System;

namespace SoapTrace.Tests
{
	/// <summary>
	/// Test fixture for the 
	/// <see cref="SoapTrace.Core.Formatters.SimpleMessageFormatter"/>.  
	/// Tests simple message formatting.
	/// </summary>
	[ TestFixture ]
	public class SimpleMessageFormatterTestFixture
	{
		/// <summary>
		/// The formatter under test.
		/// </summary>
		private SimpleMessageFormatter m_Formatter;

		/// <summary>
		/// The name of the web service which is passed to the formatter.
		/// </summary>
		private string m_WebServiceName = "Maths";

		/// <summary>
		/// The name of the web service operation which is passed to the
		/// formatter.
		/// </summary>
		private string m_WebServiceMethod = "Test";

		/// <summary>
		/// The expected formatted request xml.
		/// </summary>
		private string m_FormattedRequestXml = String.Empty;

		/// <summary>
		/// The mock soap message object that contains the message to be formatted.
		/// </summary>
		private MockSoapMessage m_MockMessage;

		/// <summary>
		/// The soap response message that will be formatted.
		/// </summary>
		private string m_SoapResponseMessage = String.Empty;

		/// <summary>
		/// The expected formatted response.
		/// </summary>
		private string m_FormattedResponseXml = String.Empty;

		/// <summary>
		/// The Http header of the message to format.
		/// </summary>
		private string m_HttpHeader = String.Empty;

		/// <summary>
		/// Initialises each test.
		/// </summary>
		[ SetUp ]
		public void Init( )
		{
			m_Formatter = new SimpleMessageFormatter( );

			m_MockMessage = new MockSoapMessage( );

			SetSoapResponseMessage( );
			SetFormattedResponseXml( );
			SetHttpHeader( );			

			// Set dummy message to return.
			m_MockMessage.SetMessage( m_SoapResponseMessage );

			// Set dummy soap header to return.
			m_MockMessage.SetHeader( m_HttpHeader );
			
		}

		/// <summary>
		/// Tests the formatting when no formatting settings are on.
		/// Should just return the plain soap message without changing it.
		/// </summary>
		[ Test ]
		public void NoFormatting( )
		{
			m_Formatter.ShowSoapHeaders = false;
			m_Formatter.ShowSoapMessageParameters = false;
			m_Formatter.FormatSoapMessage = false;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;
			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod,
				m_MockMessage );
			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( m_SoapResponseMessage, FormattedResponse, "Response xml strings do not match." );
		}

		/// <summary>
		/// Tests that the formatted soap message setting pretty prints
		/// the soap message xml.
		/// </summary>
		[ Test ]
		public void FormattedSoapMessage( )
		{
			m_Formatter.ShowSoapHeaders = false;
			m_Formatter.ShowSoapMessageParameters = false;
			m_Formatter.FormatSoapMessage = true;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;
			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod, 
				m_MockMessage );
			string FormattedResponse = FormattedText.Text;

			string ExpectedResult = ValueFormatter.IndentedFormat( m_SoapResponseMessage );

			Assert.AreEqual( ExpectedResult, FormattedResponse, "Response xml strings do not match." );
		}


		/// <summary>
		/// Tests to see if the header is added to the formatted string.
		/// </summary>
		[ Test ]
		public void HttpHeader( )
		{
			m_Formatter.ShowSoapHeaders = true;
			m_Formatter.ShowSoapMessageParameters = false;
			m_Formatter.FormatSoapMessage = false;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod, 
				m_MockMessage );

			string FormattedResponse = FormattedText.Text;
			string ExpectedResult = String.Concat( m_HttpHeader, m_SoapResponseMessage );

			Assert.AreEqual( ExpectedResult, FormattedResponse, "Response xml strings do not match." );
		}

		/// <summary>
		/// Tests that the soap message parameters settings removes
		/// the soap envelope xml.
		/// </summary>
		[ Test ]
		public void SoapMessageParameters( )
		{
			m_Formatter.ShowSoapHeaders = false;
			m_Formatter.ShowSoapMessageParameters = true;
			m_Formatter.FormatSoapMessage = false;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod, 
				m_MockMessage );
			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( m_FormattedResponseXml, FormattedResponse, "Response xml strings do not match." );
		}
		
		/// <summary>
		/// Tests that the soap envelope is removed and only
		/// the soap message body remains.</summary>
		[ Test ]
		public void FormattedNoSoapEnvelope( )
		{
			m_Formatter.ShowSoapHeaders = false;
			m_Formatter.ShowSoapMessageParameters = false;
			m_Formatter.ShowSoapEnvelope = false;
			m_Formatter.FormatSoapMessage = true;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;
			
			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod, 
				m_MockMessage );

			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( ValueFormatter.IndentedFormat( GetSoapMessageBody( ) ), 
			                FormattedResponse, 
			                "Formatted soap message body text is incorrect." );
			
		}

		/// <summary>
		/// Tests that the soap envelope is removed and only
		/// the soap message body remains.</summary>
		[ Test ]
		public void NoSoapEnvelope( )
		{
			m_Formatter.ShowSoapHeaders = false;
			m_Formatter.ShowSoapMessageParameters = false;
			m_Formatter.ShowSoapEnvelope = false;
			m_Formatter.FormatSoapMessage = false;

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;
			
			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				String.Empty,
				m_WebServiceName,
				m_WebServiceMethod, 
				m_MockMessage );

			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( GetSoapMessageBody( ), 
			                FormattedResponse, 
			                "Formatted soap message body text is incorrect." );
			
		}	
		
		/// <summary>
		/// Tests the <see cref="SimpleMessageFormatter.RemoveSoapEnvelope"/>
		/// method.
		/// </summary>
		[ Test ]
		public void RemoveSoapEnvelope( )
		{
			string Message = "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>\r\n" +
				"<soap:Body>\r\n" +
				"<Foo/>\r\n" +
				"</soap:Body>\r\n" +
				"</soap:Envelope>";
			
			Assert.AreEqual( "<Foo/>", 
			                SimpleMessageFormatter.RemoveSoapEnvelope( Message ),
			                "Did not remove soap envelope correctly." );
		}
		
		/// <summary>
		/// Tests the <see cref="SimpleMessageFormatter.RemoveSoapEnvelope"/>
		/// method.
		/// </summary>
		[ Test ]
		public void RemoveSoapEnvelopeWithDifferentNamespace( )
		{
			string Message = "<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/'>\r\n" +
				"<SOAP:Body>\r\n" +
				"<Foo/>\r\n" +
				"</SOAP:Body>\r\n" +
				"</SOAP:Envelope>";
			
			Assert.AreEqual( "<Foo/>", 
			                SimpleMessageFormatter.RemoveSoapEnvelope( Message ),
			                "Did not remove soap envelope correctly." );
		}		
		
		/// <summary>
		/// Tests the <see cref="SimpleMessageFormatter.GetSoapNamespacePrefix"/> method.
		/// </summary>
		[ Test ]
		public void SoapNamespacePrefix( )
		{
			string Message = "<?xml version='1.0' encoding='utf-8'?>\r\n" +
				"<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/'>\r\n" +
				"<SOAP:Body>\r\n" +
				"<Foo/>\r\n" +
				"</SOAP:Body>\r\n" +
				"</SOAP:Envelope>";
			
			Assert.AreEqual( "SOAP", 
			                SimpleMessageFormatter.GetSoapNamespacePrefix( Message ),
			                "Did not retrieve correct namespace prefx." );
		}
		
		/// <summary>
		/// Tests the <see cref="SimpleMessageFormatter.RemoveSoapEnvelope"/>
		/// method.
		/// </summary>
		[ Test ]
		public void RemoveSingleLineSoapEnvelope( )
		{
			string Message = "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" +
				"<soap:Body>" +
				"<Foo/>" +
				"</soap:Body>" +
				"</soap:Envelope>";
			
			Assert.AreEqual( "<Foo/>", 
			                SimpleMessageFormatter.RemoveSoapEnvelope( Message ),
			                "Did not remove soap envelope correctly." );
		}
		
		/// <summary>
		/// Set the soap messsage's soap response.
		/// </summary>
		private void SetSoapResponseMessage( )
		{
			m_SoapResponseMessage = @"<?xml version='1.0' encoding='utf-8'?>" +
				"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
				"<soap:Body>" +
				GetSoapMessageBody( ) +
				"</soap:Body>" +
				"</soap:Envelope>";
		}

		/// <summary>
		/// Gets the soap message that will be inside the
		/// soap message body element.</summary>
		private string GetSoapMessageBody( )
		{
			string Xml = "<TestResponse xmlns='http://tempuri.org/'>" +
				"<TestResult>" +
				"<string>&lt;ticket&gt;&lt;user&gt;matt&lt;/user&gt;&lt;password&gt;secret&lt;/password&gt;&lt;/ticket&gt;</string>" +
				"<string>&lt;hello&gt;world&lt;/hello&gt;</string>" +
				"</TestResult>" +
				"</TestResponse>";
			
			return Xml;
		}
		
		/// <summary>
		/// Sets the expected formatted response xml.
		/// </summary>
		private void SetFormattedResponseXml( )
		{
			m_FormattedResponseXml = "TestResponse\r\n\r\n" + 
				"<TestResult>\r\n\t<string>&lt;ticket&gt;&lt;user&gt;matt&lt;/user&gt;&lt;password&gt;secret&lt;/password&gt;&lt;/ticket&gt;</string>\r\n\t" +
				"<string>&lt;hello&gt;world&lt;/hello&gt;</string>\r\n</TestResult>\r\n\r\n";			
			
		}

		/// <summary>
		/// Sets the Http Header associated with this message.
		/// </summary>
		private void SetHttpHeader( )
		{
			m_HttpHeader = String.Concat( "POST /MathWebService/Maths.asmx HTTP/1.1\r\n",
                "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1.4322.573)",
				"Content-Type: text/xml; charset=utf-8",
				"SOAPAction: ;http://tempuri.org/Add;",
				"Content-Length: 321",
				"Expect: 100-continue",
				"Connection: Keep-Alive",
				"Host: localhost:8080" );
		}
	}
}
